package cn.e4j.modular.system.service.impl;

import cn.e4j.core.cache.CacheKey;
import cn.e4j.core.cache.CacheUtil;
import cn.e4j.core.common.exception.BizExceptionEnum;
import cn.e4j.core.dto.Dtos;
import cn.e4j.core.dto.impl.Dto;
import cn.e4j.core.util.ToolUtil;
import cn.e4j.core.util.TreeUtil;
import cn.e4j.model.exception.ServiceException;
import cn.e4j.modular.system.entity.SysModule;
import cn.e4j.modular.system.mapper.SysModuleMapper;
import cn.e4j.modular.system.service.SysModuleService;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/**
 * <p>
 * 功能模块表 服务实现类
 * </p>
 *
 * @author yuhuan
 * @since 2018-12-26
 */
@Service
public class SysModuleServiceImpl extends ServiceImpl<SysModuleMapper, SysModule> implements SysModuleService {
    @Transactional(readOnly = true)
    public List<SysModule> getModulesTree (Map<String,Object> map){
        return this.baseMapper.selectByMap(map);
    }

    @Transactional(readOnly = true)
    public List<Map<String, Object>> getModuleslist(Page<Object> page, Dto dto) {
        List<Map<String, Object>> moduleDtos = this.baseMapper.getModuleslist(page, dto);
        return moduleDtos;
    }

    /**
     * 增加
     * @param sysModule
     * @return
     */
    @Transactional
    public Dto add(SysModule sysModule){
        // 生成语义ID
        SysModule parentSysModules = this.baseMapper.getParentModule(sysModule.getPARENT_ID());
        String maxCascadeId = this.baseMapper.getMaxCascadeId(sysModule.getPARENT_ID());
        if (maxCascadeId==null) {
            String temp = "0";
            if (parentSysModules!=null) {
                temp = parentSysModules.getCASCADE_ID();
            }
            maxCascadeId = temp + ".000";
        }
        String cascade_id_ = TreeUtil.genCascadeTreeId(maxCascadeId, 999);
        sysModule.setCASCADE_ID(cascade_id_);

        sysModule.setIS_LEAF("1");
        //对关键字段入库前的trim处理
        if(ToolUtil.isNotEmpty(sysModule.getURL())){
            sysModule.setURL(sysModule.getURL().trim());
        }

        sysModule.insert();

        //更新父节点的是否叶子节点字段
        parentSysModules.setIS_LEAF("0");
        parentSysModules.updateById();

        //更新缓存
        CacheUtil.remove("'" + CacheKey.C_SYS_MODULE_GETORGSTREE + "'");
        //新的node节点
        Dto item = Dtos.newDto();
        item.put("id", sysModule.getID());
        item.put("name", sysModule.getNAME());
        item.put("parentid", sysModule.getPARENT_ID());
        item.put("code",sysModule.getCASCADE_ID());
        Dto node = Dtos.newDto();
        node.put("node",item);
        return node;
    }

    /**
     * 修改
     * @param sysModule
     */
    @Transactional
    public void edit(SysModule sysModule){
        SysModule oldSysModule = this.baseMapper.selectById(sysModule.getID());
        // 判断上级节点是否被更换
        if(oldSysModule.getPARENT_ID().equals(sysModule.getPARENT_ID())) {

            sysModule.updateById();
            //更新缓存
            CacheUtil.remove("'" + CacheKey.C_SYS_MODULE_GETORGSTREE + "'");
        } else {
            // 获取所有下级组织信息（ID和级联ID）
            List<SysModule> childList = this.baseMapper.getModuleTreeLowCascadeId(sysModule.getID());

            // 生成语义ID
            String cascade_id_ = generateCascadeId(sysModule.getPARENT_ID());

            // 更新所有下级组织的语义ID
            childList.forEach(node -> {
                String oldCascadeId = node.getCASCADE_ID();
                String newCascadeId = cascade_id_ + oldCascadeId.substring(oldCascadeId.lastIndexOf("."));
                node.setCASCADE_ID(newCascadeId);
            });
            sysModule.setCASCADE_ID(cascade_id_);

            if(this.baseMapper.getChildList(sysModule.getPARENT_ID()).size() == 0) {
                updateIsLeaf(sysModule.getPARENT_ID(),"0");
            }

            sysModule.updateById();
            childList.forEach(this::updateCascadeID);

            if(this.baseMapper.getChildList(oldSysModule.getPARENT_ID()).size() == 0) {
                updateIsLeaf(oldSysModule.getPARENT_ID(),"1");
            }
        }
    }

    private void updateIsLeaf(String ID,String isLeaf) {
        UpdateWrapper<SysModule> sysModuleUpdateWrapper = new UpdateWrapper<>();
        sysModuleUpdateWrapper.eq("ID",ID);
        SysModule updateSysModule = new SysModule();
        updateSysModule.setIS_LEAF(isLeaf);
        updateSysModule.update(sysModuleUpdateWrapper);
    }

    private void updateCascadeID(SysModule sysModule) {
        UpdateWrapper<SysModule> sysModuleUpdateWrapper = new UpdateWrapper<>();
        sysModuleUpdateWrapper.eq("ID",sysModule.getID());
        sysModule.update(sysModuleUpdateWrapper);
    }

    private String generateCascadeId(String parentId) {
        SysModule parentSysModule = this.baseMapper.selectById(parentId);
        String maxCascadeId = this.baseMapper.getMaxCascadeId(parentId);
        if (maxCascadeId==null) {
            String tempParentCascadeId = "0";
            if (parentSysModule != null) {
                tempParentCascadeId = parentSysModule.getCASCADE_ID();
            }
            maxCascadeId = tempParentCascadeId + ".000";
        }
        return TreeUtil.genCascadeTreeId(maxCascadeId, 999);
    }

    /**
     * 删除
     * @param sysModule
     */
    @Transactional
    public void delete(SysModule sysModule){
        //更新父节点的是否叶子节点属性
        List childList = this.baseMapper.getChildList(sysModule.getID());
        if(childList.size()==0){
            sysModule.deleteById();

            List parentChildList = this.baseMapper.getChildList(sysModule.getPARENT_ID());
            if(parentChildList.size() == 0){
                SysModule parentSysModule = this.baseMapper.getParentModule(sysModule.getPARENT_ID());
                parentSysModule.setIS_LEAF("1");
                parentSysModule.updateById();
            }
        }
        //更新缓存
        CacheUtil.remove("'" + CacheKey.C_SYS_MODULE_GETORGSTREE + "'");
    }

    @Transactional(readOnly = true)
    public List<SysModule> getModulesByRole(String userId) {
        List<SysModule> moduleDtos = this.baseMapper.getModulesByRole(userId);
        return moduleDtos;
    }

    @Transactional(readOnly = true)
    public List getChildList(SysModule sysModule) {
        List childList = this.baseMapper.getChildList(sysModule.getID());
        return childList;
    }
}
